package com.xms.logging.service;

import com.xms.core.enums.LogLevel;
import com.xms.core.exception.XmsUnauthorizedException;
import com.xms.dependency.XmsDependencyException;
import com.xms.logging.entity.VisitedLog;
import com.xms.security.identity.ICurrentUser;
import com.xms.utils.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * <p>
 * 应用日志服务
 * </p>
 *
 * @author migo
 * @since 2021/9/26
 */
@Service
public class AppLogging implements IAppLogging {
    private IVisitedLogService _logService;
    private ICurrentUser _currentUser;
    @Autowired
    public void AppLogging(IVisitedLogService logService,
                           ICurrentUser currentUser) {
        _logService = logService;
        _currentUser = currentUser;
    }

    private boolean create(LogLevel logLevel, String title, String description, int statusCode){
        VisitedLog entity = new VisitedLog();
        entity.setClientip("");
        entity.setUrl("");
        entity.setUrlreferrer("");
        entity.setSystemuserid(UUIDUtil.Empty);
        entity.setOrganizationid(UUIDUtil.Empty);
        if(_currentUser != null && _currentUser.getUser() != null) {
            entity.setSystemuserid(_currentUser.getUser().SystemUserId);
            entity.setClientip(_currentUser.getRequest() != null && _currentUser.getRequest().getRemoteAddr() != null ? _currentUser.getRequest().getRemoteAddr() : "");
            entity.setUrl(_currentUser.getRequest() != null && _currentUser.getRequest().getRequestURI() != null ? _currentUser.getRequest().getRequestURI() : "");
            entity.setUrlreferrer(_currentUser.getRequest() != null && _currentUser.getRequest().getHeader("referer") != null ? _currentUser.getRequest().getHeader("referer") : "");
            entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        }
        entity.setStatuscode(statusCode);
        entity.setLoglevel(logLevel.value());
        entity.setTitle(title);
        entity.setDescription(description);
        entity.setTypecode(1);
        entity.setCreatedon(LocalDateTime.now());
        entity.setVisitedlogid(UUIDUtil.get());
        return _logService.save(entity);
    }

    @Override
    public boolean info(String message) {
        return this.create(LogLevel.Information, message, "", 200);
    }

    @Override
    public boolean info(Exception exception) {
        return this.create(LogLevel.Information, exception.getMessage(), exception.getStackTrace().toString(), 200);
    }

    @Override
    public boolean warn(String message) {
        return this.create(LogLevel.Warning, message, "", 200);
    }

    @Override
    public boolean warn(Exception exception) {
        return this.create(LogLevel.Warning, exception.getMessage(), exception.getStackTrace().toString(), 200);
    }

    @Override
    public boolean error(String message) {
        return this.create(LogLevel.Error, message, "", 500);
    }

    @Override
    public boolean error(Exception exception) {
        int statusCode = 500;
        if(exception instanceof XmsUnauthorizedException){
            statusCode = XmsUnauthorizedException.STATUS_CODE;
        }
        else if(exception instanceof XmsDependencyException){
            statusCode = XmsDependencyException.STATUS_CODE;
        }
        return this.create(LogLevel.Error, exception.getMessage(), getStackTrace(exception), statusCode);
    }

    private static String getStackTrace(Exception e) {

        StringBuffer sb = new StringBuffer();
        StackTraceElement[] stackArray = e.getStackTrace();
        for (int i = 0; i < stackArray.length; i++) {
            StackTraceElement element = stackArray[i];
            sb.append(element.toString() + "\n");
        }
        return sb.toString();
    }

    private static String getStackTrace(Throwable e) {

        StringBuffer sb = new StringBuffer();
        StackTraceElement[] stackArray = e.getStackTrace();
        for (int i = 0; i < stackArray.length; i++) {
            StackTraceElement element = stackArray[i];
            sb.append(element.toString() + "\n");
        }
        return sb.toString();
    }
}
